﻿using Core.Database.Model;
using Core.Language;
using Core.Utility.Extendsions.Regex;
using Core.Utility.Extendsions.Validation;
using Core.Utility.Helper;
using Core.ValidateRules.Lib;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Core.Database
{
    /// <summary>
    /// 本地存储
    /// </summary>
    public class LocalDataStorageConfig: IDataErrorInfo, INotifyPropertyChanged
    {
        #region 数据库类型

        /// <summary>
        /// 数据库类型
        /// </summary>
        private DatabaseType? databaseType;

        /// <summary>
        /// 数据库类型
        /// </summary>
        [JsonProperty("database_type")]
        [ValidateRulesRequired(ErrorMessage = "{0}不允许为空")]
        [Display(Name = "数据库类型")]
        public DatabaseType? DatabaseType
        {
            get { return databaseType; }
            set { SetProperty(ref databaseType, value); }
        }

        #endregion 数据库类型 

        #region 连接地址

        /// <summary>
        /// 连接地址
        /// </summary>
        private string? address;

        /// <summary>
        /// 连接地址
        /// </summary>
        [JsonProperty("address")]
        [ValidateRulesRequired(ErrorMessage = "{0}不允许为空")]
        [Display(Name = "连接地址")]
        public string? Address
        {
            get { return address; }
            set
            {
                address = value;
                OnPropertyChanged();
            }
        }

        #endregion 连接地址

        #region 数据库端口

        /// <summary>
        /// 数据库端口
        /// </summary>
        private string? port;

        /// <summary>
        /// 数据库端口
        /// </summary>
        [JsonProperty("port")]
        [ValidateRulesRequired(ErrorMessage = "{0}不允许为空")]
        [Display(Name = "数据库端口")]
        [CustomValidation(typeof(LocalDataStorageConfig),nameof(PortValidate),ErrorMessage = "不合法")]
        public string? Port
        {
            get { return port; }
            set
            {
                port = value;
                OnPropertyChanged();
            }
        }

        #endregion 数据库端口

        #region 数据库名称

        /// <summary>
        /// 数据库名称
        /// </summary>
        private string? databaseName;

        /// <summary>
        /// 数据库名称
        /// </summary>
        [JsonProperty("database_name")]
        [ValidateRulesRequired(ErrorMessage = "{0}不允许为空")]
        [Display(Name = "数据库名")]
        public string? DatabaseName
        {
            get { return databaseName; }
            set
            {
                databaseName = value;
                OnPropertyChanged();
            }
        }

        #endregion 数据库名称

        #region 用户名

        /// <summary>
        /// 用户名
        /// </summary>
        private string? userName;

        /// <summary>
        /// 用户名
        /// </summary>
        [JsonProperty("user_name")]
        public string? UserName
        {
            get { return userName; }
            set
            {
                userName = value;
                OnPropertyChanged();
            }
        }

        #endregion 用户名

        #region 密码

        /// <summary>
        /// 密码
        /// </summary>
        private string? password;

        /// <summary>
        /// 密码
        /// </summary>
        [JsonProperty("password")]
        public string? Password
        {
            get { return password; }
            set
            {
                password = value;
                OnPropertyChanged();
            }
        }

        #endregion 密码

        #region 连接池最大连接数

        /// <summary>
        /// 连接池最大连接数
        /// </summary>
        private uint _maxPoolSize = 100;

        /// <summary>
        /// 连接池最大连接数,默认值100
        /// </summary>
        [JsonProperty("max_pool_size")]
        public uint MaxPoolSize
        {
            get { return _maxPoolSize; }
            set { SetProperty(ref _maxPoolSize, value); }
        }

        #endregion 连接池最大连接数 

        #region 超时时间

        /// <summary>
        /// 超时时间
        /// </summary>
        private uint _timeout = 60;

        /// <summary>
        /// 超时时间
        /// </summary>
        [JsonProperty("timeout")]
        public uint Timeout
        {
            get { return _timeout; }
            set { SetProperty(ref _timeout, value); }
        }

        #endregion 超时时间 

        /// <summary>
        /// 端口自定义验证则
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public static ValidationResult? PortValidate(object obj, ValidationContext context)
        {
            //验证通过
            if(context.MemberName == nameof(Port))
            {
                if(obj is not null)
                {
                    string str = obj?.ToString() ?? "";
                    if (!Regex.IsMatch(str, RegexPatterns.PortPattern))
                    {
                        return new ValidationResult(LanguageResource.StringFormat("端口验证错误：{0} 不在 0 - 65535 的有效端口范围", args: new[] {obj} ));
                    }
                }
                else
                {
                    return new ValidationResult($"端口验证错误：{obj}不是一个有效的端口");
                }
            }
            return ValidationResult.Success;
        }

        /// <summary>
        /// 隐式转换 将<see cref="LocalDataStorageConfig"/> 转换为 <see cref="DatabaseConfig"/>
        /// </summary>
        /// <param name="dataStorageConfig"></param>
        public static implicit operator DatabaseConfig(LocalDataStorageConfig? dataStorageConfig)
        {
            if (dataStorageConfig == null)
            {
                return new DatabaseConfig();
            }
            return new DatabaseConfig()
            {
                ConnectionName = "本地存储",
                Address = dataStorageConfig.Address,
                DatabaseName = dataStorageConfig.DatabaseName,
                DatabaseType = EnumHelper.EnumValueToEnum<DatabaseType>(dataStorageConfig.DatabaseType.GetValueOrDefault(Core.Database.Model.DatabaseType.Sqlite).ToInt()),
                MaxPoolSize = dataStorageConfig.MaxPoolSize,
                Port = dataStorageConfig.Port?.ToString(),
                UserName = dataStorageConfig.UserName,
                Password = dataStorageConfig.Password,
                Timeout = dataStorageConfig.Timeout,
            };
        }

        /// <summary>
        /// 隐式转换 将<see cref="LocalDataStorageConfig"/> 转换为 <see cref="DatabaseConfig"/>
        /// </summary>
        /// <param name="dataStorageConfig"></param>
        public static implicit operator LocalDataStorageConfig(DatabaseConfig? dataStorageConfig)
        {
            if(dataStorageConfig == null)
            {
                return null;
            }
            return new LocalDataStorageConfig()
            {
                Address = dataStorageConfig.Address,
                DatabaseName = dataStorageConfig.DatabaseName,
                DatabaseType = EnumHelper.EnumValueToEnum<DatabaseType>(dataStorageConfig.DatabaseType.GetValueOrDefault(Core.Database.Model.DatabaseType.Sqlite).ToInt()),
                MaxPoolSize = dataStorageConfig.MaxPoolSize.ToUInt(1),
                Port = dataStorageConfig.Port,
                UserName = dataStorageConfig.UserName,
                Password = dataStorageConfig.Password,
                Timeout = dataStorageConfig.Timeout,
            };
        }

        #region 加解密
        /// <summary>
        /// 加密当前数据库配置
        /// </summary>
        /// <returns></returns>
        public LocalDataStorageConfig Encrypt()
        {
            LocalDataStorageConfig res = Encrypt(this);
            return res;
        }


        /// <summary>
        /// 解密数据库配置
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public LocalDataStorageConfig Decrypt()
        {
            LocalDataStorageConfig res = Decrypt(this);
            return res;
        }

        /// <summary>
        /// 加密数据库配置
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static LocalDataStorageConfig Encrypt(LocalDataStorageConfig config)
        {

            if (!string.IsNullOrWhiteSpace(config?.Address))
            {
                config.Address = DatabaseFactory.Encrypt(config.Address, nameof(config.Address) + "_LocalDataStorageConfig");
            }

            if (!string.IsNullOrWhiteSpace(config?.Port))
            {
                config.Port = DatabaseFactory.Encrypt(config?.Port?.ToString(), nameof(config.Port) + "_LocalDataStorageConfig");
            }

            if (!string.IsNullOrWhiteSpace(config?.UserName))
            {
                config.UserName = DatabaseFactory.Encrypt(config.UserName, nameof(config.UserName) + "_LocalDataStorageConfig");
            }

            if (!string.IsNullOrWhiteSpace(config?.Password))
            {
                config.Password = DatabaseFactory.Encrypt(config.Password, nameof(config.Password) + "_LocalDataStorageConfig");
            }
            return config;
        }

        /// <summary>
        /// 解密数据库配置
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static LocalDataStorageConfig? Decrypt(LocalDataStorageConfig? config)
        {
            if (!string.IsNullOrWhiteSpace(config?.Address))
            {
                config.Address = DatabaseFactory.Decrypt(config.Address, nameof(config.Address) + "_LocalDataStorageConfig");
            }

            if (!string.IsNullOrWhiteSpace(config?.Port))
            {
                config.Port = DatabaseFactory.Decrypt(config?.Port?.ToString(), nameof(config.Port) + "_LocalDataStorageConfig");
            }

            if (!string.IsNullOrWhiteSpace(config?.UserName))
            {
                config.UserName = DatabaseFactory.Decrypt(config.UserName, nameof(config.UserName) + "_LocalDataStorageConfig");
            }

            if (!string.IsNullOrWhiteSpace(config?.Password))
            {
                config.Password = DatabaseFactory.Decrypt(config.Password, nameof(config.Password) + "_LocalDataStorageConfig");
            }
            return config;
        }
        #endregion 加解密

        public override bool Equals(object? obj)
        {
            if(obj is LocalDataStorageConfig model)
            {
                if(model.DatabaseName == DatabaseName
                    && model.DatabaseType == DatabaseType
                    && model.Address == Address
                    && model.Port ==  Port
                    && model.UserName == UserName
                    && model.Password == Password
                    && model.MaxPoolSize == MaxPoolSize)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #region VM相关
        #region 错误信息校验相关

        #region 自定义错误信息
        /// <summary>
        /// 自定义验证错误信息
        /// </summary>
        private readonly Dictionary<string, ICollection<string>> _customValidationErrorList = new Dictionary<string, ICollection<string>>();

        /// <summary>
        /// 清除自定义错误信息
        /// </summary>
        public void ClearCustomValidationErrorList()
        {
            _customValidationErrorList.Clear();
        }

        /// <summary>
        /// 添加错误信息，错误列表将被替换
        /// </summary>
        /// <param name="errorMessageList">错误信息列表</param>
        /// <param name="propertyName">属性名称</param>
        public void AddCustomValidationError(ICollection<string> errorMessageList, [CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                if (_customValidationErrorList.ContainsKey(propertyName))
                {
                    _customValidationErrorList[propertyName] = errorMessageList;
                }
                else
                {
                    _customValidationErrorList.Add(propertyName, errorMessageList);
                }
            }
        }

        /// <summary>
        /// 添加错误信息，在错误列表的基础上继续追加
        /// </summary>
        /// <param name="errorMessage"></param>
        /// <param name="propertyName"></param>
        public void AddCustomValidationError(string errorMessage, [CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                if (_customValidationErrorList.ContainsKey(propertyName))
                {
                    _customValidationErrorList[propertyName].Add(propertyName);
                }
                else
                {
                    _customValidationErrorList.Add(propertyName, new List<string>() { errorMessage });
                }
            }
        }

        /// <summary>
        /// 移除错误信息
        /// </summary>
        /// <param name="propertyName"></param>
        public void RemoveCustomValidationError([CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                if (_customValidationErrorList.ContainsKey(propertyName))
                {
                    _customValidationErrorList[propertyName].Remove(propertyName);
                }
            }
        }
        #endregion 自定义错误信息

        /// <summary>
        /// 错误
        /// </summary>
        public string Error
        {
            get
            {
                string res = "";
                var validRes = ValidResult();
                if (!validRes.IsValid)
                {
                    res = validRes.ErrorMessages.ToString();
                }
                if (_customValidationErrorList?.Count > 0 && _customValidationErrorList.Where(p => p.Value.Count() > 0).Count() > 0)
                {
                    StringBuilder errorMessageStringBuilder = new StringBuilder();
                    foreach (var errorItem in _customValidationErrorList.Values)
                    {
                        foreach (var error in errorItem)
                        {
                            errorMessageStringBuilder.AppendLine(error);
                        }
                    }
                }
                return res;
            }
        }

        #region 验证结果信息

        /// <summary>
        /// 验证结果信息
        /// </summary>
        private ValidationResultInfo _validationResultInfo = new ValidationResultInfo();

        /// <summary>
        /// 验证结果信息
        /// </summary>
        public ValidationResultInfo ValidationResultInfo
        {
            get { return _validationResultInfo; }
            private set { SetProperty(ref _validationResultInfo, value); }
        }

        #endregion 验证结果信息 

        /// <summary>
        /// 数据有效验证结果
        /// </summary>
        /// <returns></returns>
        public virtual ValidationExtensionsResult ValidResult()
        {
            ValidationExtensionsResult result = ValidatetionExtensions.ValidResult(this);
            //进行自定义错误校验
            if (_customValidationErrorList?.Count > 0 && _customValidationErrorList.Where(p => p.Value.Count() > 0).Count() > 0)
            {
                result.IsValid = false;
                StringBuilder errorMessageStringBuilder = new StringBuilder();
                List<ErrorMember> errorMemberList = new List<ErrorMember>();
                foreach (var errorItem in _customValidationErrorList)
                {
                    foreach (var error in errorItem.Value)
                    {
                        var errorMember = new ErrorMember();
                        errorMember.ErrorMemberName = errorItem.Key;
                        errorMember.ErrorMessage = error;
                        errorMemberList.Add(errorMember);
                    }
                }
                if (result.ErrorMessages != null && result.ErrorMessages.Count() > 0)
                {
                    result.ErrorMembers.AddRange(errorMemberList);
                }
                else
                {
                    result.ErrorMembers = errorMemberList;
                }
            }
            ValidationResultInfo = new ValidationResultInfo(result.IsValid);
            ValidationResultInfo.ErrorInfo = result.ErrorMessages;
            return result;
        }

        /// <summary>
        /// 数据有效验证结果
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual ValidationExtensionsResult ValidResult(object obj)
        {
            return ValidatetionExtensions.ValidResult(obj);
        }

        public virtual string this[string columnName]
        {
            get
            {
                var vc = new ValidationContext(this, null, null);
                vc.MemberName = columnName;
                var res = new List<ValidationResult>();
                var result = Validator.TryValidateProperty(this.GetType()?.GetProperty(columnName)?.GetValue(this, null), vc, res);
                ValidResult();
                if (res.Count > 0)
                {
                    return string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
                }
                return string.Empty;
            }
        }

        #region 自定义校验示例
        //private string? _sampleValidateField;
        //[Required]
        //[ValidateRulesStringLength(60)]
        //[DisplayName("示例验证字段")]
        //[CustomValidation(typeof(BaseModel), nameof(SampleValidate))]
        //public string SampleValidateField
        //{
        //    get { return _sampleValidateField; }
        //    set { _sampleValidateField = value; RaisePropertyChanged(nameof(SampleValidateField)); }
        //}

        ///// <summary>
        ///// 自定义验证示例规则
        ///// </summary>
        ///// <param name="obj"></param>
        ///// <param name="context"></param>
        ///// <returns></returns>
        //public static ValidationResult SampleValidate(object obj, ValidationContext context)
        //{
        //    var model = (BaseModel)context.ObjectInstance;
        //    if (model.Error != model.SampleValidateField)
        //    {
        //        return new ValidationResult("这是一个示例验证字段的错误信息",
        //            new List<string> { nameof(SampleValidateField), "某个错误属性名称" });
        //    }
        //    //验证通过
        //    return ValidationResult.Success;
        //}
        #endregion 自定义校验示例

        #endregion 错误信息校验相关

        public event PropertyChangedEventHandler? PropertyChanged;

        /// <summary>
        /// 实现通知更新
        /// </summary>
        /// <param name="propertyName"></param>
        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// 设置属性，实现通知
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
            {
                return false;
            }

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        /// <summary>
        /// 设置属性，实现通知
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="onChanged"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
            {
                return false;
            }

            storage = value;
            onChanged?.Invoke();
            OnPropertyChanged(propertyName);
            return true;
        }
        #endregion VM相关
    }
}
